#!/usr/bin/env bash

[ -n "$LKP_SRC" ] ||
export LKP_SRC=$(dirname $(dirname $(readlink -e -v $0)))

. $LKP_SRC/lib/result.sh
. $LKP_SRC/lib/lkp_cmd.sh
. $LKP_SRC/lib/env.sh
. $LKP_SRC/lib/tbox.sh
. $LKP_SRC/lib/constant.sh
. $LKP_SRC/lib/lkp_path.sh

if ! [ $(id -u) = 0 ]; then
	echo "This script must be run as root" 1>&2
	exit 1
fi

script_name=$(basename $0)

[ -n "$HOSTNAME" ] || HOSTNAME=$(hostname)		#?chomp
[ -n "$LKP_SRC" ] || export LKP_SRC=$(dirname $(dirname $(readlink -e -v $0)))
TMP="$LKP_SRC/tmp"

usage() {
	echo "Usage: lkp $script_name [options] [<script>/<jobfile>]"
	echo "options: "
	echo "-f|--force: force to install testsuites"
	echo "--hdd partition: HDD partition for IO tests"
	echo "--ssd partition: SSD partition for IO tests"
	echo "--dry-run: preview changes will made testbox by install"
	echo "--china: install gem packages from the mirror in China"
	echo "--skip-base: skip to install base support"
	echo "--help: show this message"
}

hdd_index=1
ssd_index=1

while [ $# -gt 0 ]
do
	case "$1" in
		--help)
		usage
		exit
		;;
		--hdd)
		hdd_partitions[$hdd_index]=$2
		hdd_index=$((hdd_index+1))
		shift
		;;
		--ssd)
		ssd_partitions[$ssd_index]=$2
		ssd_index=$((ssd_index+1))
		shift
		;;
		--dry-run)
		DRY_RUN=0
		;;
		--china)
		CHINA=0
		;;
		--force|-f)
		FORCE_MODE=true
		;;
		*)
		break
		;;
	esac
	shift
done

check_yaml_file()
{
	local filename=$1
	if [ -f $filename ]; then
		grep -q '^arch: ' $filename || {
			echo "only atomic jobs can be installed" >&2
			echo "Please run lkp split-job $filename first" >&2
			exit 1
		}
	else
		echo "$0: cannot find file $filename" >&2
		exit 1
	fi
}

make_wakeup() {
	[ -d "$LKP_SRC/bin/event" ] || return 0	# 'lkp docker build' uses a temp LKP_SRC, we should make in the final LKP_SRC
	[ -x "$LKP_SRC/bin/event/wakeup" ] && return 0

	echo "make -C $LKP_SRC/bin/event"
	[ -n "$DRY_RUN" ] && return

	make -C "$LKP_SRC/bin/event" wakeup || exit
}

# todo: make paths configurable and less intrusive to developer's system
# currently it's hard coded in a number of places, should be changed together
create_lkp_dirs() {
	[ -n "$DRY_RUN" ] && return

	mkdir -p $TMP
	mkdir -p $KTEST_PATHS_DIR
	mkdir -p '/lkp/benchmarks'
}

bundle_install() {
	local ruby_version=$(ruby --version)
	if [[ "$ruby_version" != "${ruby_version#ruby 3}" ]]; then
		bundle install
	elif [[ "$ruby_version" != "${ruby_version#ruby 2.0}" ]]; then
		# centos 7
		cmd='gem install git:1.7.0 concurrent-ruby:1.1.9 i18n:1.4.0 minitest:5.11.3 activesupport:4.2.11.3 '
		echo $cmd
		$cmd
	elif [[ "$ruby_version" != "${ruby_version#ruby 2}" ]]; then
		BUNDLE_GEMFILE=Gemfile.2 bundle install
	else
		echo "unknown ruby version: $ruby_version"
		exit 1
	fi
}

bundle_install_china() {
	local tmpdir=$(mktemp -d /tmp/lkp-install-china-XXXXXX)
	trap "rm -rf $tmpdir" EXIT
	cp $LKP_SRC/Gemfile* $tmpdir/
	(cd $tmpdir || exit; bundle config --local mirror.https://rubygems.org https://gems.ruby-china.com; bundle_install)
}

makepkg_install() {
	local pkg=$1
	local force_opt=
	local path="$LKP_SRC/pkg/$pkg/PKGBUILD"

	[ -n "$FORCE_MODE" ] && force_opt="-f"

	[ -f "$path" ] || path=$LKP_SRC/programs/$pkg/PKGBUILD
	[ -f "$path" ] || path=$LKP_SRC/monitors/$pkg/PKGBUILD
	[ -f "$path" ] || path=($LKP_SRC/programs/*/PKGBUILD-$pkg)
	[ -f "$path" ] || path=($LKP_SRC/monitors/*/PKGBUILD-$pkg)
	[ -f "$path" ] || {
		echo "Failed to find PKGBUILD path for $pkg"
		return 1
	}

	if [ -f "$path" ]; then
		(
			cd "$(dirname $path)" || exit
			echo "Building package with: $path"
			PACMAN="$LKP_SRC/sbin/pacman-LKP" CARCH=$arch BUILDDIR="$HOME/.cache/lkp/pkg-builddir" \
			"$LKP_SRC/sbin/makepkg" --config "$(lkp_src)/etc/makepkg.conf" -s -i --skippgpcheck "$force_opt" \
			-p $(basename $path)
		)
	else
		return 0
	fi
}

verify_install() {
	local pkg=$1
	case $DISTRO in
		debian|ubuntu)
			[[ ! $(dpkg -V "$pkg" 2>&1) ]] || [[ ! $(dpkg -V "$pkg-lkp" 2>&1) ]];;
		centos|fedora|openeuler)
			[[ ! $(rpm -V "$pkg" 2>&1) ]] || [[ ! $(rpm -V "$pkg-lkp" 2>&1) ]];;
		*)
			return 1;;
	esac
}

make_install_packages() {
	for pkg
	do
		verify_install $pkg && continue
		makepkg_install "$pkg" && continue

		echo "Failed to install package '$pkg'"
		exit 1
	done
}

install_packages() {
	local generic_packages="$*"

	[ -n "$DRY_RUN" ] && {
		echo "Installing packages with: $LKP_SRC/distro/installer $distro $generic_packages"
		return
	}

	if [ "$distro" = "centos" -o "$distro" = "aliyun" ]; then
		local ocfs2_tools_name=$(echo "$generic_packages" | grep 'ocfs2-tools')
		if [ -n "$ocfs2_tools_name" ]; then
			install_ocfs2_tools "$ocfs2_tools_name"
		fi
	fi

	$LKP_SRC/distro/installer $distro $generic_packages || {
		echo "Cannot install some packages in $LKP_SRC/distro/depends/${script}"
		exit 1
	}
}

install_base_support()
{
	echo "Installing ruby gems..."

	if [ -n "$CHINA" ]; then
		setup_gem_china
	fi
	(
		cd "$LKP_SRC"  || exit
		bundle_install || exit
	) || exit

	create_lkp_user
	create_lkp_dirs
}

. $LKP_SRC/lib/install.sh
. $LKP_SRC/distro/common

detect_system
distro=$_system_name_lowercase

DISTRO=$distro
export DISTRO

load_distro_funcs $distro

export LKP_LOCAL_RUN=1
create_host_config

if [[ -z "$1" ]]; then
	install_base_support
	all_scripts='lkp-tests makepkg'
else
	make_wakeup
	all_scripts=
fi

for filename in "$@"
do
	if [ ${filename##*.} = "yaml" ]; then
		check_yaml_file $filename
		parse_yaml $filename
		all_scripts+=" $scripts "
	elif [ -e "$LKP_SRC/depends/$filename" 	]; then all_scripts+=" $filename "
	elif [ -d "$LKP_SRC/setup/$filename" 	]; then all_scripts+=" $filename "
	elif [ -d "$LKP_SRC/programs/$filename" ]; then all_scripts+=" $filename "
	elif [ -d "$LKP_SRC/monitors/$filename" ]; then all_scripts+=" $filename "
	else
		glob=($LKP_SRC/*/run-$filename)
		if test -f "$glob"; then
			all_scripts+=" $filename "
		else
			echo "$0: skip unknown parameter $filename" >&2
			exit 1
		fi
	fi
done

mapping=$($LKP_SRC/sbin/pkgmap --to-os="$distro@$_system_version" $all_scripts)
pip_packages=$(echo "$mapping" | grep "^pip: " | cut -f2 -d:)
gem_packages=$(echo "$mapping" | grep "^gem: " | cut -f2 -d:)
os_packages=$(echo "$mapping" | grep "^os: " | cut -f2 -d:)
pkgbuild_packages=$(echo "$mapping" | grep "^PKGBUILD: " | cut -f2 -d:)

pip_packages=${pip_packages# }
gem_packages=${gem_packages# }

[ -n "$pip_packages" ] && os_packages+=" python3-pip "
install_packages $os_packages
[ -n "$pip_packages" ] && { pip3 install $pip_packages || exit; }
[ -n "$gem_packages" ] && { gem install $gem_packages || exit; }
make_install_packages $pkgbuild_packages
exit 0
